Quick overview

Current status

#library(nCov2019)
library(leaflet)
library(dplyr)
library(ggplot2)
library(plotly)
library(scales)
library(xts)
library(dygraphs)
library(corrplot)
COVID<-read.csv("covid_19_data.csv")
COVID_2<-read.csv("COVID19_7-Apr.csv")

Format date:

Date<-as.Date(COVID_2$Date, format="%m/%d/%y") 

COVID_2$Date2<-Date
COVID_updated<-COVID_2 %>% filter(Date2==max(Date2))
leaflet(width = "100%") %>% 
  addProviderTiles("CartoDB.DarkMatter") %>% 
  setView(lng = 0, lat = 10, zoom = 1.5) %>% 
  addCircleMarkers(data = COVID_updated, 
                   lng = ~ Long,
                   lat = ~ Lat,
                   radius = ~ log(Confirmed+1),
                   color = rgb(218/255,65/255,56/255),
                   fillOpacity = ~ ifelse(Confirmed > 0, 1, 0),
                   stroke = FALSE,
                   label = ~ paste(Province.State,",",Country.Region, ": ", Confirmed)
                   )

Current top 10 countries:

COVID_top<-COVID_2 %>% filter(Date2==max(Date2)) %>% 
  group_by(Country.Region) %>% summarise(Total_confirmed=sum(Confirmed)) %>% 
  top_n(10,Total_confirmed) %>% arrange(desc(Total_confirmed))
plot<-ggplot(data=COVID_top
       , aes(x=Total_confirmed,y=reorder(Country.Region,Total_confirmed))) +
  geom_bar(stat ="identity",alpha=0.8,fill="firebrick3") +
  geom_text(aes(label=Total_confirmed), vjust=0.5, hjust=0.9,color="black", size=3.5) +
  scale_x_continuous(labels = comma) +
  labs(title = paste("Top 10 countries with confirmed cases as of ",max(COVID_2$Date2)),
       x = "Confirmed cases",
       y = "Country") +
  theme_minimal()

ggplotly(plot,tooltip = c("x"),width=750)

Time distribution:

COVID_2_Day<- COVID_2 %>% group_by(Date2) %>% summarise(World_confirmed=sum(Confirmed),
                                                        World_deaths=sum(Deaths),
                                                        World_recovered=sum(Recovered))


COVID_Day_confirmed_series<-xts(COVID_2_Day$World_confirmed, order.by=COVID_2_Day$Date2)
COVID_Day_deaths_series<-xts(COVID_2_Day$World_deaths, order.by=COVID_2_Day$Date2)
COVID_Day_recovered_series<-xts(COVID_2_Day$World_recovered, order.by=COVID_2_Day$Date2)

Day_summary<-cbind(COVID_Day_confirmed_series,COVID_Day_deaths_series,COVID_Day_recovered_series)
dygraph(Day_summary, main = "SARS-COV2-outbreak: Total worldwide cases", 
        xlab="Date", ylab="Total cases",width = 750) %>% 
  dySeries("COVID_Day_confirmed_series", "Total cases",drawPoints = TRUE, 
           pointSize = 3, color=rgb(53/255,116/255,199/255)) %>% 
  dySeries("COVID_Day_deaths_series", "Total deaths",drawPoints = TRUE, 
           pointSize = 3, color=rgb(189/255,55/255,48/255)) %>% 
  dySeries("COVID_Day_recovered_series", "Total recovered",drawPoints = TRUE, 
           pointSize = 3, color=rgb(69/255,136/255,51/255)) %>% 
  dyRangeSelector()

Team members countries total cases:

COVID_2_Day_Lebanon<- COVID_2 %>% 
  filter(Country.Region %in% c("Lebanon")) %>% 
  group_by(Date2) %>% summarise(World_confirmed=sum(Confirmed))

COVID_2_Day_Chile<- COVID_2 %>% 
  filter(Country.Region %in% c("Chile")) %>% 
  group_by(Date2) %>% summarise(World_confirmed=sum(Confirmed))

COVID_2_Day_Colombia<- COVID_2 %>% 
  filter(Country.Region %in% c("Colombia")) %>% 
  group_by(Date2) %>% summarise(World_confirmed=sum(Confirmed))

COVID_2_Day_CostaRica<- COVID_2 %>% 
  filter(Country.Region %in% c("Costa Rica")) %>% 
  group_by(Date2) %>% summarise(World_confirmed=sum(Confirmed))


COVID_Day_series_Lebanon<-xts(COVID_2_Day_Lebanon$World_confirmed, order.by=COVID_2_Day_Lebanon$Date2)
COVID_Day_series_Chile<-xts(COVID_2_Day_Chile$World_confirmed, order.by=COVID_2_Day_Chile$Date2)
COVID_Day_series_Colombia<-xts(COVID_2_Day_Colombia$World_confirmed, order.by=COVID_2_Day_Colombia$Date2)
COVID_Day_series_CostaRica<-xts(COVID_2_Day_CostaRica$World_confirmed, order.by=COVID_2_Day_CostaRica$Date2)

Our_Countries<-cbind(COVID_Day_series_Lebanon,COVID_Day_series_Chile,COVID_Day_series_Colombia,COVID_Day_series_CostaRica)
dygraph(Our_Countries, main = "SARS-COV2-outbreak: Total cases by country", xlab="Date", ylab="Total cases",width = 750) %>% 
  dySeries("COVID_Day_series_Lebanon", "Lebanon",drawPoints = TRUE, 
           pointSize = 3, color=rgb(0,0,3/255)) %>% 
  dySeries("COVID_Day_series_Chile", "Chile",drawPoints = TRUE, 
           pointSize = 3,color=rgb(120/255,28/255,109/255)) %>% 
  dySeries("COVID_Day_series_Colombia", "Colombia",drawPoints = TRUE, 
           pointSize = 3,color=rgb(237/255,105/255,37/255)) %>% 
  dySeries("COVID_Day_series_CostaRica", "Costa Rica",drawPoints = TRUE,
           pointSize = 3,color=rgb(204/255,197/255,126/255)) %>% 
  dyRangeSelector()

Looking for correlations

fig <- plot_ly(COVID_updated, x = ~Confirmed, y = ~Deaths, z = ~Recovered, width=750) %>% 
  add_markers(text= ~Country.Region ,hoverinfo= "text",
              marker = list(color=rgb(189/255,55/255,48/255))) %>% 
  layout(title="Confirmed cases Vs. Deaths Vs. Recovered", scene = list(
                    xaxis = list(title = 'Confirmed'),
                     yaxis = list(title = 'Deaths'),
                     zaxis = list(title = 'Recovered'))) 
fig

Human Development Index

HDI<-read.csv("Human Development Index (HDI)_2.csv",sep=";",dec=",")
COVID_Country<-COVID_2 %>% filter(Date2==max(Date2)) %>% 
  group_by(Country.Region) %>% summarise(Total_confirmed=sum(Confirmed),
                                         Total_deaths=sum(Deaths),
                                         Total_Recovered=sum(Recovered))

Remove after parentheses:

HDI$Country_2<-gsub("\\s*\\([^\\)]+\\)","",as.character(HDI$Country))
HDI$Country_2[HDI$Country_2=="United States"]<-"US"
HDI$Country_2[HDI$Country_2=="Korea"]<-"South Korea"

Population:

Population<-read.csv("World_population.csv",sep=";",dec=",")

Remove after commma:

Population$Country_Name_2<-gsub(",.*", "", as.character(Population$Country_Name))
Population$Country_Name_2[Population$Country_Name_2=="United States"]<-"US"
Population$Country_Name_2[Population$Country_Code=="KOR"]<-"South Korea"
Population$Country_Name_2[Population$Country_Code=="CZE"]<-"Czechia"

Natural Join:

COVID_3<- COVID_Country %>% inner_join(HDI,by=c("Country.Region"="Country_2")) %>% 
  inner_join(Population,by=c("Country.Region"="Country_Name_2")) %>% 
  select(Country.Region,Total_confirmed,Total_deaths,Total_Recovered,HDI_Rank_2018,Year_2018,
         Country_Code,Population_2018) %>% 
  mutate(Cases_million=(Total_confirmed/Population_2018)*1000000,
         Recovered_percentage=(Total_Recovered/Total_confirmed)*100)  

COVID_3<-COVID_3[!is.na(COVID_3$Population_2018),]

Plot the Human Development Index(HDI) Vs. the number of cases (applying a log transformation), and the proportion of recovered cases:

plot<-ggplot(data=COVID_3,aes(x=log(Cases_million),y=Year_2018,
                        size=Recovered_percentage,text=Country.Region)) +
  geom_point(color="black",fill=rgb(237/255,105/255,37/255),shape=21,alpha=0.6) +
  scale_size(range = c(3,15), name="Recovered \n percentage") +
  theme_minimal() + 
  theme(legend.position="bottom") +
  labs(title="HDI Vs. logarithmus of COVID-19 cases by million inhabitants \n and proportion of recovered",
       x="ln(Cases/1M population)",
       y="HDI")

ggplotly(plot,tooltip = c("text"),width=750)
COVID_numeric_1<-COVID_3 %>% mutate(Log_cases=log(Cases_million),
                                    Death_percentage=(Total_deaths/Total_confirmed)*100) %>% 
  select(Log_cases,Recovered_percentage,Death_percentage,Year_2018)

corrplot(cor(COVID_numeric_1),method = "number",tl.col="black",tl.srt=15,
         col=colorRampPalette(c(rgb(204/255,197/255,126/255),rgb(237/255,105/255,37/255)))(200))

Infants lacking immunization, measles (% of one-year-olds)

Measles<-read.csv("Measles_immunization.csv",sep=";",dec=".")
Measles$Country_2<-gsub("\\s*\\([^\\)]+\\)","",as.character(Measles$Country))
Measles$Country_2[Measles$Country_2=="United States"]<-"US"
Measles$Country_2[Measles$Country_2=="Korea"]<-"South Korea"
COVID_3<- COVID_3 %>% inner_join(Measles,by=c("Country.Region"="Country_2")) %>% select(-c("Country"))

#write.csv(COVID_3,"COVID_Covariables.csv")
ggplot(COVID_3, aes(y=Measles_2018)) + 
  geom_boxplot(fill="dodgerblue4",outlier.shape = 21, 
               outlier.fill = "firebrick",alpha=0.75) +
  ggtitle("Boxplot of % infants lacking measles immunization") + ylab("% of infants") +
  theme_minimal()

ggplot(COVID_3, aes(Measles_2018)) + 
  geom_histogram(fill="dodgerblue4",bins=20,alpha=0.8) +
  ggtitle("Histogram of % infants lacking measles immunization") + 
  xlab("% of infants") + 
  ylab("Count") +
  theme_minimal()

plot<-ggplot(data=COVID_3,aes(x=log(Cases_million),y=Measles_2018,
                        size=Recovered_percentage,text=Country.Region)) +
  geom_point(color="black",fill=rgb(120/255,28/255,109/255),shape=21,alpha=0.6) +
  scale_size(range = c(3,15), name="Recovered \n percentage") +
  theme_minimal() + 
  theme(legend.position="bottom") +
  labs(title="% infants lacking measles immunization Vs. logarithmus of COVID-19 cases by million inhabitants \n and proportion of recovered",
       x="ln(Cases/1M population)",
       y="% of infants")

ggplotly(plot,tooltip = c("text"),width=750)

Health expenditure (% of GDP)

Health_expenditure<-read.csv("Health_expenditure_GDP.csv",sep=";",dec=".")
Health_expenditure$Country_2<-gsub("\\s*\\([^\\)]+\\)","",
                                   as.character(Health_expenditure$Country))
Health_expenditure$Country_2[Health_expenditure$Country_2=="United States"]<-"US"
Health_expenditure$Country_2[Health_expenditure$Country_2=="Korea"]<-"South Korea"
COVID_3<- COVID_3 %>% inner_join(Health_expenditure,by=c("Country.Region"="Country_2")) %>% select(-c("Country"))

#write.csv(COVID_3,"COVID_Covariables.csv")
plot<-ggplot(data=COVID_3,aes(x=log(Cases_million),y=Expenditure_2016,
                        size=Recovered_percentage,text=Country.Region)) +
  geom_point(color="black",fill=rgb(204/255,197/255,126/255),shape=21,alpha=0.6) +
  scale_size(range = c(3,15), name="Recovered \n percentage") +
  theme_minimal() + 
  theme(legend.position="bottom") +
  labs(title="Health expenditure (% of GDP) Vs. logarithmus of COVID-19 cases by million inhabitants \n and proportion of recovered",
       x="ln(Cases/1M population)",
       y="% of GDP in health")

ggplotly(plot,tooltip = c("text"),width=750)

Fitting a regression model

Mod1<-lm(log(COVID_3$Cases_million)~COVID_3$Year_2018+COVID_3$Measles_2018+COVID_3$Expenditure_2016)
summary(Mod1)

Call:
lm(formula = log(COVID_3$Cases_million) ~ COVID_3$Year_2018 + 
    COVID_3$Measles_2018 + COVID_3$Expenditure_2016)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.2724 -0.7267 -0.0046  0.8119  4.1725 

Coefficients:
                          Estimate Std. Error t value Pr(>|t|)    
(Intercept)              -6.779882   0.663669 -10.216  < 2e-16 ***
COVID_3$Year_2018        13.294002   0.837850  15.867  < 2e-16 ***
COVID_3$Measles_2018      0.011153   0.009456   1.179  0.24005    
COVID_3$Expenditure_2016  0.117851   0.042104   2.799  0.00579 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.273 on 152 degrees of freedom
Multiple R-squared:  0.7306,    Adjusted R-squared:  0.7253 
F-statistic: 137.4 on 3 and 152 DF,  p-value: < 2.2e-16
hist(Mod1$residuals)

shapiro.test(Mod1$residuals)

    Shapiro-Wilk normality test

data:  Mod1$residuals
W = 0.98965, p-value = 0.3087
LS0tCnRpdGxlOiAiQ09WSUQtMTkgT3V0YnJlYWs6IFdvcmxkd2lkZSBhbmFseXNpcyIKYXV0aG9yOiAiQW91biwgQ2FtYXJnbywgTWFydGluZXosUm9kcmlndWV6IgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgdGhlbWU6IGNvc21vCiAgICAgCi0tLQohW10oQ29yb25hdmlydXMuanBnKQoKIyBRdWljayBvdmVydmlldwoKIyMgQ3VycmVudCBzdGF0dXMKCgpgYGB7cixtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9CiNsaWJyYXJ5KG5Db3YyMDE5KQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHh0cykKbGlicmFyeShkeWdyYXBocykKbGlicmFyeShjb3JycGxvdCkKYGBgCgpgYGB7cn0KQ09WSUQ8LXJlYWQuY3N2KCJjb3ZpZF8xOV9kYXRhLmNzdiIpCkNPVklEXzI8LXJlYWQuY3N2KCJDT1ZJRDE5XzctQXByLmNzdiIpCmBgYAoKRm9ybWF0IGRhdGU6CmBgYHtyfQpEYXRlPC1hcy5EYXRlKENPVklEXzIkRGF0ZSwgZm9ybWF0PSIlbS8lZC8leSIpIAoKQ09WSURfMiREYXRlMjwtRGF0ZQpgYGAKCmBgYHtyfQpDT1ZJRF91cGRhdGVkPC1DT1ZJRF8yICU+JSBmaWx0ZXIoRGF0ZTI9PW1heChEYXRlMikpCmBgYAoKYGBge3J9CmxlYWZsZXQod2lkdGggPSAiMTAwJSIpICU+JSAKICBhZGRQcm92aWRlclRpbGVzKCJDYXJ0b0RCLkRhcmtNYXR0ZXIiKSAlPiUgCiAgc2V0VmlldyhsbmcgPSAwLCBsYXQgPSAxMCwgem9vbSA9IDEuNSkgJT4lIAogIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IENPVklEX3VwZGF0ZWQsIAogICAgICAgICAgICAgICAgICAgbG5nID0gfiBMb25nLAogICAgICAgICAgICAgICAgICAgbGF0ID0gfiBMYXQsCiAgICAgICAgICAgICAgICAgICByYWRpdXMgPSB+IGxvZyhDb25maXJtZWQrMSksCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHJnYigyMTgvMjU1LDY1LzI1NSw1Ni8yNTUpLAogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSB+IGlmZWxzZShDb25maXJtZWQgPiAwLCAxLCAwKSwKICAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgbGFiZWwgPSB+IHBhc3RlKFByb3ZpbmNlLlN0YXRlLCIsIixDb3VudHJ5LlJlZ2lvbiwgIjogIiwgQ29uZmlybWVkKQogICAgICAgICAgICAgICAgICAgKQpgYGAKCkN1cnJlbnQgdG9wIDEwIGNvdW50cmllczoKYGBge3J9CkNPVklEX3RvcDwtQ09WSURfMiAlPiUgZmlsdGVyKERhdGUyPT1tYXgoRGF0ZTIpKSAlPiUgCiAgZ3JvdXBfYnkoQ291bnRyeS5SZWdpb24pICU+JSBzdW1tYXJpc2UoVG90YWxfY29uZmlybWVkPXN1bShDb25maXJtZWQpKSAlPiUgCiAgdG9wX24oMTAsVG90YWxfY29uZmlybWVkKSAlPiUgYXJyYW5nZShkZXNjKFRvdGFsX2NvbmZpcm1lZCkpCmBgYAoKYGBge3J9CnBsb3Q8LWdncGxvdChkYXRhPUNPVklEX3RvcAogICAgICAgLCBhZXMoeD1Ub3RhbF9jb25maXJtZWQseT1yZW9yZGVyKENvdW50cnkuUmVnaW9uLFRvdGFsX2NvbmZpcm1lZCkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ImlkZW50aXR5IixhbHBoYT0wLjgsZmlsbD0iZmlyZWJyaWNrMyIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPVRvdGFsX2NvbmZpcm1lZCksIHZqdXN0PTAuNSwgaGp1c3Q9MC45LGNvbG9yPSJibGFjayIsIHNpemU9My41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJUb3AgMTAgY291bnRyaWVzIHdpdGggY29uZmlybWVkIGNhc2VzIGFzIG9mICIsbWF4KENPVklEXzIkRGF0ZTIpKSwKICAgICAgIHggPSAiQ29uZmlybWVkIGNhc2VzIiwKICAgICAgIHkgPSAiQ291bnRyeSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmdncGxvdGx5KHBsb3QsdG9vbHRpcCA9IGMoIngiKSx3aWR0aD03NTApCmBgYAoKVGltZSBkaXN0cmlidXRpb246CmBgYHtyfQpDT1ZJRF8yX0RheTwtIENPVklEXzIgJT4lIGdyb3VwX2J5KERhdGUyKSAlPiUgc3VtbWFyaXNlKFdvcmxkX2NvbmZpcm1lZD1zdW0oQ29uZmlybWVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXb3JsZF9kZWF0aHM9c3VtKERlYXRocyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV29ybGRfcmVjb3ZlcmVkPXN1bShSZWNvdmVyZWQpKQoKCkNPVklEX0RheV9jb25maXJtZWRfc2VyaWVzPC14dHMoQ09WSURfMl9EYXkkV29ybGRfY29uZmlybWVkLCBvcmRlci5ieT1DT1ZJRF8yX0RheSREYXRlMikKQ09WSURfRGF5X2RlYXRoc19zZXJpZXM8LXh0cyhDT1ZJRF8yX0RheSRXb3JsZF9kZWF0aHMsIG9yZGVyLmJ5PUNPVklEXzJfRGF5JERhdGUyKQpDT1ZJRF9EYXlfcmVjb3ZlcmVkX3NlcmllczwteHRzKENPVklEXzJfRGF5JFdvcmxkX3JlY292ZXJlZCwgb3JkZXIuYnk9Q09WSURfMl9EYXkkRGF0ZTIpCgpEYXlfc3VtbWFyeTwtY2JpbmQoQ09WSURfRGF5X2NvbmZpcm1lZF9zZXJpZXMsQ09WSURfRGF5X2RlYXRoc19zZXJpZXMsQ09WSURfRGF5X3JlY292ZXJlZF9zZXJpZXMpCmBgYAoKCmBgYHtyfQpkeWdyYXBoKERheV9zdW1tYXJ5LCBtYWluID0gIlNBUlMtQ09WMi1vdXRicmVhazogVG90YWwgd29ybGR3aWRlIGNhc2VzIiwgCiAgICAgICAgeGxhYj0iRGF0ZSIsIHlsYWI9IlRvdGFsIGNhc2VzIix3aWR0aCA9IDc1MCkgJT4lIAogIGR5U2VyaWVzKCJDT1ZJRF9EYXlfY29uZmlybWVkX3NlcmllcyIsICJUb3RhbCBjYXNlcyIsZHJhd1BvaW50cyA9IFRSVUUsIAogICAgICAgICAgIHBvaW50U2l6ZSA9IDMsIGNvbG9yPXJnYig1My8yNTUsMTE2LzI1NSwxOTkvMjU1KSkgJT4lIAogIGR5U2VyaWVzKCJDT1ZJRF9EYXlfZGVhdGhzX3NlcmllcyIsICJUb3RhbCBkZWF0aHMiLGRyYXdQb2ludHMgPSBUUlVFLCAKICAgICAgICAgICBwb2ludFNpemUgPSAzLCBjb2xvcj1yZ2IoMTg5LzI1NSw1NS8yNTUsNDgvMjU1KSkgJT4lIAogIGR5U2VyaWVzKCJDT1ZJRF9EYXlfcmVjb3ZlcmVkX3NlcmllcyIsICJUb3RhbCByZWNvdmVyZWQiLGRyYXdQb2ludHMgPSBUUlVFLCAKICAgICAgICAgICBwb2ludFNpemUgPSAzLCBjb2xvcj1yZ2IoNjkvMjU1LDEzNi8yNTUsNTEvMjU1KSkgJT4lIAogIGR5UmFuZ2VTZWxlY3RvcigpCmBgYAoKClRlYW0gbWVtYmVycyBjb3VudHJpZXMgdG90YWwgY2FzZXM6CmBgYHtyfQpDT1ZJRF8yX0RheV9MZWJhbm9uPC0gQ09WSURfMiAlPiUgCiAgZmlsdGVyKENvdW50cnkuUmVnaW9uICVpbiUgYygiTGViYW5vbiIpKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZTIpICU+JSBzdW1tYXJpc2UoV29ybGRfY29uZmlybWVkPXN1bShDb25maXJtZWQpKQoKQ09WSURfMl9EYXlfQ2hpbGU8LSBDT1ZJRF8yICU+JSAKICBmaWx0ZXIoQ291bnRyeS5SZWdpb24gJWluJSBjKCJDaGlsZSIpKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZTIpICU+JSBzdW1tYXJpc2UoV29ybGRfY29uZmlybWVkPXN1bShDb25maXJtZWQpKQoKQ09WSURfMl9EYXlfQ29sb21iaWE8LSBDT1ZJRF8yICU+JSAKICBmaWx0ZXIoQ291bnRyeS5SZWdpb24gJWluJSBjKCJDb2xvbWJpYSIpKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZTIpICU+JSBzdW1tYXJpc2UoV29ybGRfY29uZmlybWVkPXN1bShDb25maXJtZWQpKQoKQ09WSURfMl9EYXlfQ29zdGFSaWNhPC0gQ09WSURfMiAlPiUgCiAgZmlsdGVyKENvdW50cnkuUmVnaW9uICVpbiUgYygiQ29zdGEgUmljYSIpKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZTIpICU+JSBzdW1tYXJpc2UoV29ybGRfY29uZmlybWVkPXN1bShDb25maXJtZWQpKQoKCkNPVklEX0RheV9zZXJpZXNfTGViYW5vbjwteHRzKENPVklEXzJfRGF5X0xlYmFub24kV29ybGRfY29uZmlybWVkLCBvcmRlci5ieT1DT1ZJRF8yX0RheV9MZWJhbm9uJERhdGUyKQpDT1ZJRF9EYXlfc2VyaWVzX0NoaWxlPC14dHMoQ09WSURfMl9EYXlfQ2hpbGUkV29ybGRfY29uZmlybWVkLCBvcmRlci5ieT1DT1ZJRF8yX0RheV9DaGlsZSREYXRlMikKQ09WSURfRGF5X3Nlcmllc19Db2xvbWJpYTwteHRzKENPVklEXzJfRGF5X0NvbG9tYmlhJFdvcmxkX2NvbmZpcm1lZCwgb3JkZXIuYnk9Q09WSURfMl9EYXlfQ29sb21iaWEkRGF0ZTIpCkNPVklEX0RheV9zZXJpZXNfQ29zdGFSaWNhPC14dHMoQ09WSURfMl9EYXlfQ29zdGFSaWNhJFdvcmxkX2NvbmZpcm1lZCwgb3JkZXIuYnk9Q09WSURfMl9EYXlfQ29zdGFSaWNhJERhdGUyKQoKT3VyX0NvdW50cmllczwtY2JpbmQoQ09WSURfRGF5X3Nlcmllc19MZWJhbm9uLENPVklEX0RheV9zZXJpZXNfQ2hpbGUsQ09WSURfRGF5X3Nlcmllc19Db2xvbWJpYSxDT1ZJRF9EYXlfc2VyaWVzX0Nvc3RhUmljYSkKCmBgYAoKYGBge3J9CmR5Z3JhcGgoT3VyX0NvdW50cmllcywgbWFpbiA9ICJTQVJTLUNPVjItb3V0YnJlYWs6IFRvdGFsIGNhc2VzIGJ5IGNvdW50cnkiLCB4bGFiPSJEYXRlIiwgeWxhYj0iVG90YWwgY2FzZXMiLHdpZHRoID0gNzUwKSAlPiUgCiAgZHlTZXJpZXMoIkNPVklEX0RheV9zZXJpZXNfTGViYW5vbiIsICJMZWJhbm9uIixkcmF3UG9pbnRzID0gVFJVRSwgCiAgICAgICAgICAgcG9pbnRTaXplID0gMywgY29sb3I9cmdiKDAsMCwzLzI1NSkpICU+JSAKICBkeVNlcmllcygiQ09WSURfRGF5X3Nlcmllc19DaGlsZSIsICJDaGlsZSIsZHJhd1BvaW50cyA9IFRSVUUsIAogICAgICAgICAgIHBvaW50U2l6ZSA9IDMsY29sb3I9cmdiKDEyMC8yNTUsMjgvMjU1LDEwOS8yNTUpKSAlPiUgCiAgZHlTZXJpZXMoIkNPVklEX0RheV9zZXJpZXNfQ29sb21iaWEiLCAiQ29sb21iaWEiLGRyYXdQb2ludHMgPSBUUlVFLCAKICAgICAgICAgICBwb2ludFNpemUgPSAzLGNvbG9yPXJnYigyMzcvMjU1LDEwNS8yNTUsMzcvMjU1KSkgJT4lIAogIGR5U2VyaWVzKCJDT1ZJRF9EYXlfc2VyaWVzX0Nvc3RhUmljYSIsICJDb3N0YSBSaWNhIixkcmF3UG9pbnRzID0gVFJVRSwKICAgICAgICAgICBwb2ludFNpemUgPSAzLGNvbG9yPXJnYigyMDQvMjU1LDE5Ny8yNTUsMTI2LzI1NSkpICU+JSAKICBkeVJhbmdlU2VsZWN0b3IoKQpgYGAKCgojIExvb2tpbmcgZm9yIGNvcnJlbGF0aW9ucwoKYGBge3J9CmZpZyA8LSBwbG90X2x5KENPVklEX3VwZGF0ZWQsIHggPSB+Q29uZmlybWVkLCB5ID0gfkRlYXRocywgeiA9IH5SZWNvdmVyZWQsIHdpZHRoPTc1MCkgJT4lIAogIGFkZF9tYXJrZXJzKHRleHQ9IH5Db3VudHJ5LlJlZ2lvbiAsaG92ZXJpbmZvPSAidGV4dCIsCiAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvcj1yZ2IoMTg5LzI1NSw1NS8yNTUsNDgvMjU1KSkpICU+JSAKICBsYXlvdXQodGl0bGU9IkNvbmZpcm1lZCBjYXNlcyBWcy4gRGVhdGhzIFZzLiBSZWNvdmVyZWQiLCBzY2VuZSA9IGxpc3QoCiAgICAgICAgICAgICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0NvbmZpcm1lZCcpLAogICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnRGVhdGhzJyksCiAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICdSZWNvdmVyZWQnKSkpIApmaWcKYGBgCgojIyBIdW1hbiBEZXZlbG9wbWVudCBJbmRleAoKYGBge3J9CkhESTwtcmVhZC5jc3YoIkh1bWFuIERldmVsb3BtZW50IEluZGV4IChIREkpXzIuY3N2IixzZXA9IjsiLGRlYz0iLCIpCmBgYAoKYGBge3J9CkNPVklEX0NvdW50cnk8LUNPVklEXzIgJT4lIGZpbHRlcihEYXRlMj09bWF4KERhdGUyKSkgJT4lIAogIGdyb3VwX2J5KENvdW50cnkuUmVnaW9uKSAlPiUgc3VtbWFyaXNlKFRvdGFsX2NvbmZpcm1lZD1zdW0oQ29uZmlybWVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUb3RhbF9kZWF0aHM9c3VtKERlYXRocyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG90YWxfUmVjb3ZlcmVkPXN1bShSZWNvdmVyZWQpKQpgYGAKClJlbW92ZSBhZnRlciBwYXJlbnRoZXNlczoKYGBge3J9CkhESSRDb3VudHJ5XzI8LWdzdWIoIlxccypcXChbXlxcKV0rXFwpIiwiIixhcy5jaGFyYWN0ZXIoSERJJENvdW50cnkpKQpgYGAKCmBgYHtyfQpIREkkQ291bnRyeV8yW0hESSRDb3VudHJ5XzI9PSJVbml0ZWQgU3RhdGVzIl08LSJVUyIKSERJJENvdW50cnlfMltIREkkQ291bnRyeV8yPT0iS29yZWEiXTwtIlNvdXRoIEtvcmVhIgpgYGAKClBvcHVsYXRpb246CmBgYHtyfQpQb3B1bGF0aW9uPC1yZWFkLmNzdigiV29ybGRfcG9wdWxhdGlvbi5jc3YiLHNlcD0iOyIsZGVjPSIsIikKYGBgCgpSZW1vdmUgYWZ0ZXIgY29tbW1hOgpgYGB7cn0KUG9wdWxhdGlvbiRDb3VudHJ5X05hbWVfMjwtZ3N1YigiLC4qIiwgIiIsIGFzLmNoYXJhY3RlcihQb3B1bGF0aW9uJENvdW50cnlfTmFtZSkpCmBgYAoKYGBge3J9ClBvcHVsYXRpb24kQ291bnRyeV9OYW1lXzJbUG9wdWxhdGlvbiRDb3VudHJ5X05hbWVfMj09IlVuaXRlZCBTdGF0ZXMiXTwtIlVTIgpQb3B1bGF0aW9uJENvdW50cnlfTmFtZV8yW1BvcHVsYXRpb24kQ291bnRyeV9Db2RlPT0iS09SIl08LSJTb3V0aCBLb3JlYSIKUG9wdWxhdGlvbiRDb3VudHJ5X05hbWVfMltQb3B1bGF0aW9uJENvdW50cnlfQ29kZT09IkNaRSJdPC0iQ3plY2hpYSIKYGBgCgpOYXR1cmFsIEpvaW46CmBgYHtyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRX0KQ09WSURfMzwtIENPVklEX0NvdW50cnkgJT4lIGlubmVyX2pvaW4oSERJLGJ5PWMoIkNvdW50cnkuUmVnaW9uIj0iQ291bnRyeV8yIikpICU+JSAKICBpbm5lcl9qb2luKFBvcHVsYXRpb24sYnk9YygiQ291bnRyeS5SZWdpb24iPSJDb3VudHJ5X05hbWVfMiIpKSAlPiUgCiAgc2VsZWN0KENvdW50cnkuUmVnaW9uLFRvdGFsX2NvbmZpcm1lZCxUb3RhbF9kZWF0aHMsVG90YWxfUmVjb3ZlcmVkLEhESV9SYW5rXzIwMTgsWWVhcl8yMDE4LAogICAgICAgICBDb3VudHJ5X0NvZGUsUG9wdWxhdGlvbl8yMDE4KSAlPiUgCiAgbXV0YXRlKENhc2VzX21pbGxpb249KFRvdGFsX2NvbmZpcm1lZC9Qb3B1bGF0aW9uXzIwMTgpKjEwMDAwMDAsCiAgICAgICAgIFJlY292ZXJlZF9wZXJjZW50YWdlPShUb3RhbF9SZWNvdmVyZWQvVG90YWxfY29uZmlybWVkKSoxMDApICAKCkNPVklEXzM8LUNPVklEXzNbIWlzLm5hKENPVklEXzMkUG9wdWxhdGlvbl8yMDE4KSxdCgpgYGAKClBsb3QgdGhlIEh1bWFuIERldmVsb3BtZW50IEluZGV4KEhESSkgVnMuIHRoZSBudW1iZXIgb2YgY2FzZXMgKGFwcGx5aW5nIGEgbG9nIHRyYW5zZm9ybWF0aW9uKSwgYW5kIHRoZSBwcm9wb3J0aW9uIG9mIHJlY292ZXJlZCBjYXNlczoKYGBge3J9CnBsb3Q8LWdncGxvdChkYXRhPUNPVklEXzMsYWVzKHg9bG9nKENhc2VzX21pbGxpb24pLHk9WWVhcl8yMDE4LAogICAgICAgICAgICAgICAgICAgICAgICBzaXplPVJlY292ZXJlZF9wZXJjZW50YWdlLHRleHQ9Q291bnRyeS5SZWdpb24pKSArCiAgZ2VvbV9wb2ludChjb2xvcj0iYmxhY2siLGZpbGw9cmdiKDIzNy8yNTUsMTA1LzI1NSwzNy8yNTUpLHNoYXBlPTIxLGFscGhhPTAuNikgKwogIHNjYWxlX3NpemUocmFuZ2UgPSBjKDMsMTUpLCBuYW1lPSJSZWNvdmVyZWQgXG4gcGVyY2VudGFnZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBsYWJzKHRpdGxlPSJIREkgVnMuIGxvZ2FyaXRobXVzIG9mIENPVklELTE5IGNhc2VzIGJ5IG1pbGxpb24gaW5oYWJpdGFudHMgXG4gYW5kIHByb3BvcnRpb24gb2YgcmVjb3ZlcmVkIiwKICAgICAgIHg9ImxuKENhc2VzLzFNIHBvcHVsYXRpb24pIiwKICAgICAgIHk9IkhESSIpCgpnZ3Bsb3RseShwbG90LHRvb2x0aXAgPSBjKCJ0ZXh0Iiksd2lkdGg9NzUwKQpgYGAKCgpgYGB7cn0KQ09WSURfbnVtZXJpY18xPC1DT1ZJRF8zICU+JSBtdXRhdGUoTG9nX2Nhc2VzPWxvZyhDYXNlc19taWxsaW9uKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVhdGhfcGVyY2VudGFnZT0oVG90YWxfZGVhdGhzL1RvdGFsX2NvbmZpcm1lZCkqMTAwKSAlPiUgCiAgc2VsZWN0KExvZ19jYXNlcyxSZWNvdmVyZWRfcGVyY2VudGFnZSxEZWF0aF9wZXJjZW50YWdlLFllYXJfMjAxOCkKCmNvcnJwbG90KGNvcihDT1ZJRF9udW1lcmljXzEpLG1ldGhvZCA9ICJudW1iZXIiLHRsLmNvbD0iYmxhY2siLHRsLnNydD0xNSwKICAgICAgICAgY29sPWNvbG9yUmFtcFBhbGV0dGUoYyhyZ2IoMjA0LzI1NSwxOTcvMjU1LDEyNi8yNTUpLHJnYigyMzcvMjU1LDEwNS8yNTUsMzcvMjU1KSkpKDIwMCkpCmBgYAoKIyMgSW5mYW50cyBsYWNraW5nIGltbXVuaXphdGlvbiwgbWVhc2xlcyAoJSBvZiBvbmUteWVhci1vbGRzKQoKYGBge3J9Ck1lYXNsZXM8LXJlYWQuY3N2KCJNZWFzbGVzX2ltbXVuaXphdGlvbi5jc3YiLHNlcD0iOyIsZGVjPSIuIikKYGBgCgpgYGB7cn0KTWVhc2xlcyRDb3VudHJ5XzI8LWdzdWIoIlxccypcXChbXlxcKV0rXFwpIiwiIixhcy5jaGFyYWN0ZXIoTWVhc2xlcyRDb3VudHJ5KSkKYGBgCgpgYGB7cn0KTWVhc2xlcyRDb3VudHJ5XzJbTWVhc2xlcyRDb3VudHJ5XzI9PSJVbml0ZWQgU3RhdGVzIl08LSJVUyIKTWVhc2xlcyRDb3VudHJ5XzJbTWVhc2xlcyRDb3VudHJ5XzI9PSJLb3JlYSJdPC0iU291dGggS29yZWEiCmBgYAoKCmBgYHtyfQpDT1ZJRF8zPC0gQ09WSURfMyAlPiUgaW5uZXJfam9pbihNZWFzbGVzLGJ5PWMoIkNvdW50cnkuUmVnaW9uIj0iQ291bnRyeV8yIikpICU+JSBzZWxlY3QoLWMoIkNvdW50cnkiKSkKCiN3cml0ZS5jc3YoQ09WSURfMywiQ09WSURfQ292YXJpYWJsZXMuY3N2IikKYGBgCgoKYGBge3J9CmdncGxvdChDT1ZJRF8zLCBhZXMoeT1NZWFzbGVzXzIwMTgpKSArIAogIGdlb21fYm94cGxvdChmaWxsPSJkb2RnZXJibHVlNCIsb3V0bGllci5zaGFwZSA9IDIxLCAKICAgICAgICAgICAgICAgb3V0bGllci5maWxsID0gImZpcmVicmljayIsYWxwaGE9MC43NSkgKwogIGdndGl0bGUoIkJveHBsb3Qgb2YgJSBpbmZhbnRzIGxhY2tpbmcgbWVhc2xlcyBpbW11bml6YXRpb24iKSArIHlsYWIoIiUgb2YgaW5mYW50cyIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KZ2dwbG90KENPVklEXzMsIGFlcyhNZWFzbGVzXzIwMTgpKSArIAogIGdlb21faGlzdG9ncmFtKGZpbGw9ImRvZGdlcmJsdWU0IixiaW5zPTIwLGFscGhhPTAuOCkgKwogIGdndGl0bGUoIkhpc3RvZ3JhbSBvZiAlIGluZmFudHMgbGFja2luZyBtZWFzbGVzIGltbXVuaXphdGlvbiIpICsgCiAgeGxhYigiJSBvZiBpbmZhbnRzIikgKyAKICB5bGFiKCJDb3VudCIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KcGxvdDwtZ2dwbG90KGRhdGE9Q09WSURfMyxhZXMoeD1sb2coQ2FzZXNfbWlsbGlvbikseT1NZWFzbGVzXzIwMTgsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9UmVjb3ZlcmVkX3BlcmNlbnRhZ2UsdGV4dD1Db3VudHJ5LlJlZ2lvbikpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsZmlsbD1yZ2IoMTIwLzI1NSwyOC8yNTUsMTA5LzI1NSksc2hhcGU9MjEsYWxwaGE9MC42KSArCiAgc2NhbGVfc2l6ZShyYW5nZSA9IGMoMywxNSksIG5hbWU9IlJlY292ZXJlZCBcbiBwZXJjZW50YWdlIikgKwogIHRoZW1lX21pbmltYWwoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogIGxhYnModGl0bGU9IiUgaW5mYW50cyBsYWNraW5nIG1lYXNsZXMgaW1tdW5pemF0aW9uIFZzLiBsb2dhcml0aG11cyBvZiBDT1ZJRC0xOSBjYXNlcyBieSBtaWxsaW9uIGluaGFiaXRhbnRzIFxuIGFuZCBwcm9wb3J0aW9uIG9mIHJlY292ZXJlZCIsCiAgICAgICB4PSJsbihDYXNlcy8xTSBwb3B1bGF0aW9uKSIsCiAgICAgICB5PSIlIG9mIGluZmFudHMiKQoKZ2dwbG90bHkocGxvdCx0b29sdGlwID0gYygidGV4dCIpLHdpZHRoPTc1MCkKYGBgCgojIyBIZWFsdGggZXhwZW5kaXR1cmUgKCUgb2YgR0RQKQoKYGBge3J9CkhlYWx0aF9leHBlbmRpdHVyZTwtcmVhZC5jc3YoIkhlYWx0aF9leHBlbmRpdHVyZV9HRFAuY3N2IixzZXA9IjsiLGRlYz0iLiIpCmBgYAoKYGBge3J9CkhlYWx0aF9leHBlbmRpdHVyZSRDb3VudHJ5XzI8LWdzdWIoIlxccypcXChbXlxcKV0rXFwpIiwiIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5jaGFyYWN0ZXIoSGVhbHRoX2V4cGVuZGl0dXJlJENvdW50cnkpKQpgYGAKCmBgYHtyfQpIZWFsdGhfZXhwZW5kaXR1cmUkQ291bnRyeV8yW0hlYWx0aF9leHBlbmRpdHVyZSRDb3VudHJ5XzI9PSJVbml0ZWQgU3RhdGVzIl08LSJVUyIKSGVhbHRoX2V4cGVuZGl0dXJlJENvdW50cnlfMltIZWFsdGhfZXhwZW5kaXR1cmUkQ291bnRyeV8yPT0iS29yZWEiXTwtIlNvdXRoIEtvcmVhIgpgYGAKCgpgYGB7cn0KQ09WSURfMzwtIENPVklEXzMgJT4lIGlubmVyX2pvaW4oSGVhbHRoX2V4cGVuZGl0dXJlLGJ5PWMoIkNvdW50cnkuUmVnaW9uIj0iQ291bnRyeV8yIikpICU+JSBzZWxlY3QoLWMoIkNvdW50cnkiKSkKCiN3cml0ZS5jc3YoQ09WSURfMywiQ09WSURfQ292YXJpYWJsZXMuY3N2IikKYGBgCgpgYGB7cn0KcGxvdDwtZ2dwbG90KGRhdGE9Q09WSURfMyxhZXMoeD1sb2coQ2FzZXNfbWlsbGlvbikseT1FeHBlbmRpdHVyZV8yMDE2LAogICAgICAgICAgICAgICAgICAgICAgICBzaXplPVJlY292ZXJlZF9wZXJjZW50YWdlLHRleHQ9Q291bnRyeS5SZWdpb24pKSArCiAgZ2VvbV9wb2ludChjb2xvcj0iYmxhY2siLGZpbGw9cmdiKDIwNC8yNTUsMTk3LzI1NSwxMjYvMjU1KSxzaGFwZT0yMSxhbHBoYT0wLjYpICsKICBzY2FsZV9zaXplKHJhbmdlID0gYygzLDE1KSwgbmFtZT0iUmVjb3ZlcmVkIFxuIHBlcmNlbnRhZ2UiKSArCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgbGFicyh0aXRsZT0iSGVhbHRoIGV4cGVuZGl0dXJlICglIG9mIEdEUCkgVnMuIGxvZ2FyaXRobXVzIG9mIENPVklELTE5IGNhc2VzIGJ5IG1pbGxpb24gaW5oYWJpdGFudHMgXG4gYW5kIHByb3BvcnRpb24gb2YgcmVjb3ZlcmVkIiwKICAgICAgIHg9ImxuKENhc2VzLzFNIHBvcHVsYXRpb24pIiwKICAgICAgIHk9IiUgb2YgR0RQIGluIGhlYWx0aCIpCgpnZ3Bsb3RseShwbG90LHRvb2x0aXAgPSBjKCJ0ZXh0Iiksd2lkdGg9NzUwKQpgYGAKCgoKIyBGaXR0aW5nIGEgcmVncmVzc2lvbiBtb2RlbAoKYGBge3J9Ck1vZDE8LWxtKGxvZyhDT1ZJRF8zJENhc2VzX21pbGxpb24pfkNPVklEXzMkWWVhcl8yMDE4K0NPVklEXzMkTWVhc2xlc18yMDE4K0NPVklEXzMkRXhwZW5kaXR1cmVfMjAxNikKc3VtbWFyeShNb2QxKQpgYGAKYGBge3J9Cmhpc3QoTW9kMSRyZXNpZHVhbHMpCnNoYXBpcm8udGVzdChNb2QxJHJlc2lkdWFscykKYGBgCgoKCgoKCg==